<!DOCTYPE html>
<html lang="en">
  <head>
    <title>
        Java-Se-多线程-2-高级 - rulerLwx Blog
      </title>
        <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
      content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui">
    <meta name="renderer" content="webkit">
    <meta http-equiv="Cache-Control" content="no-transform" />
    <meta http-equiv="Cache-Control" content="no-siteapp" />
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="format-detection" content="telephone=no,email=no,adress=no">
    
    <meta name="theme-color" content="#000000" />
    
    <meta http-equiv="window-target" content="_top" />
    
    
    <meta name="description" content="CAS CAS 是什么 compareAndSet()方法，也就是 compareAndSwap ，比较并且交换。 使用示例： AtomicInteger atomicInteger = new AtomicInteger(5); //当前值是5，如果主内存中的值还是5则设置当前值" />
    <meta name="generator" content="Hugo 0.73.0 with theme pure" />
    <title>Java-Se-多线程-2-高级 - rulerLwx Blog</title>
    
    
    <link rel="stylesheet" href="https://rulerLwx.gitee.io/css/style.min.c4bc7071f132c964c2116bca53b392933f377e5ca7b7051ed245187c621a2d3e.css">
    
    <link rel="stylesheet" href="https://cdn.staticfile.org/highlight.js/9.15.10/styles/github.min.css" async>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.4.2/tocbot.css" async>
    <meta property="og:title" content="Java-Se-多线程-2-高级" />
<meta property="og:description" content="CAS CAS 是什么 compareAndSet()方法，也就是 compareAndSwap ，比较并且交换。 使用示例： AtomicInteger atomicInteger = new AtomicInteger(5); //当前值是5，如果主内存中的值还是5则设置当前值" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://rulerLwx.gitee.io/2020/07/java-se-%E5%A4%9A%E7%BA%BF%E7%A8%8B-2-%E9%AB%98%E7%BA%A7/" />
<meta property="article:published_time" content="2020-07-01T18:58:47+08:00" />
<meta property="article:modified_time" content="2020-07-01T18:58:47+08:00" />
<meta itemprop="name" content="Java-Se-多线程-2-高级">
<meta itemprop="description" content="CAS CAS 是什么 compareAndSet()方法，也就是 compareAndSwap ，比较并且交换。 使用示例： AtomicInteger atomicInteger = new AtomicInteger(5); //当前值是5，如果主内存中的值还是5则设置当前值">
<meta itemprop="datePublished" content="2020-07-01T18:58:47&#43;08:00" />
<meta itemprop="dateModified" content="2020-07-01T18:58:47&#43;08:00" />
<meta itemprop="wordCount" content="3821">



<meta itemprop="keywords" content="多线程," /><meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="Java-Se-多线程-2-高级"/>
<meta name="twitter:description" content="CAS CAS 是什么 compareAndSet()方法，也就是 compareAndSwap ，比较并且交换。 使用示例： AtomicInteger atomicInteger = new AtomicInteger(5); //当前值是5，如果主内存中的值还是5则设置当前值"/>

    <!--[if lte IE 9]>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.1.20170427/classList.min.js"></script>
      <![endif]-->

    <!--[if lt IE 9]>
        <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
      <![endif]-->
  </head>

  
  

  <body class="main-center theme-black" itemscope itemtype="http://schema.org/WebPage"><header class="header" itemscope itemtype="http://schema.org/WPHeader">
    <div class="slimContent">
      <div class="navbar-header">
        <div class="profile-block text-center">
          <a id="avatar" href="https://gitee.com/rulerLwx" target="_blank">
            <img class="img-circle img-rotate" src="https://rulerLwx.gitee.io/avatar.png" width="200" height="200">
          </a>
          <h2 id="name" class="hidden-xs hidden-sm">rulerLwx</h2>
          <h3 id="title" class="hidden-xs hidden-sm hidden-md">thinking...</h3>
          <small id="location" class="text-muted hidden-xs hidden-sm"><i class="icon icon-map-marker"></i>Guangzhou, China</small>
        </div><div class="search" id="search-form-wrap">
    <form class="search-form sidebar-form">
        <div class="input-group">
            <input type="text" class="search-form-input form-control" placeholder="Search" />
            <span class="input-group-btn">
                <button type="submit" class="search-form-submit btn btn-flat" onclick="return false;"><i
                        class="icon icon-search"></i></button>
            </span>
        </div>
        <div class="ins-search">
            <div class="ins-search-mask"></div>
            <div class="ins-search-container">
                <div class="ins-input-wrapper">
                    <input type="text" class="ins-search-input" placeholder="Type something..."
                        x-webkit-speech />
                    <button type="button" class="close ins-close ins-selectable" data-dismiss="modal"
                        aria-label="Close"><span aria-hidden="true">×</span></button>
                </div>
                <div class="ins-section-wrapper">
                    <div class="ins-section-container"></div>
                </div>
            </div>
        </div>
    </form>
</div>
        <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#main-navbar" aria-controls="main-navbar" aria-expanded="false">
          <span class="sr-only">Toggle navigation</span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
      </div>
      <nav id="main-navbar" class="collapse navbar-collapse" itemscope itemtype="http://schema.org/SiteNavigationElement" role="navigation">
        <ul class="nav navbar-nav main-nav">
            <li class="menu-item menu-item-home">
                <a href="/">
                    <i class="icon icon-home-fill"></i>
                  <span class="menu-title">Home</span>
                </a>
            </li>
            <li class="menu-item menu-item-archives">
                <a href="/posts/">
                    <i class="icon icon-archives-fill"></i>
                  <span class="menu-title">Archives</span>
                </a>
            </li>
            <li class="menu-item menu-item-categories">
                <a href="/categories/">
                    <i class="icon icon-folder"></i>
                  <span class="menu-title">Categories</span>
                </a>
            </li>
            <li class="menu-item menu-item-tags">
                <a href="/tags/">
                    <i class="icon icon-tags"></i>
                  <span class="menu-title">Tags</span>
                </a>
            </li>
            <li class="menu-item menu-item-about">
                <a href="/about/">
                    <i class="icon icon-cup-fill"></i>
                  <span class="menu-title">About</span>
                </a>
            </li>
        </ul>
      </nav>
    </div>
  </header>

<aside class="sidebar" itemscope itemtype="http://schema.org/WPSideBar">
  <div class="slimContent">
    
      <div class="widget">
    <h3 class="widget-title">Board</h3>
    <div class="widget-body">
        <div id="board">
            <div class="content">enjoy~
            </div>
        </div>
    </div>
</div>

      <div class="widget">
    <h3 class="widget-title"> Categories</h3>
    <div class="widget-body">
        <ul class="category-list">
            <li class="category-list-item"><a href="https://rulerLwx.gitee.io/categories/java-framework/" class="category-list-link">java-framework</a><span class="category-list-count">38</span></li>
            <li class="category-list-item"><a href="https://rulerLwx.gitee.io/categories/java-front-end/" class="category-list-link">java-front-end</a><span class="category-list-count">11</span></li>
            <li class="category-list-item"><a href="https://rulerLwx.gitee.io/categories/java-se/" class="category-list-link">java-se</a><span class="category-list-count">21</span></li>
            <li class="category-list-item"><a href="https://rulerLwx.gitee.io/categories/java-senior/" class="category-list-link">java-senior</a><span class="category-list-count">4</span></li>
            <li class="category-list-item"><a href="https://rulerLwx.gitee.io/categories/linux/" class="category-list-link">linux</a><span class="category-list-count">13</span></li>
            <li class="category-list-item"><a href="https://rulerLwx.gitee.io/categories/tools/" class="category-list-link">tools</a><span class="category-list-count">1</span></li>
            <li class="category-list-item"><a href="https://rulerLwx.gitee.io/categories/%E6%8A%80%E6%9C%AF%E6%9D%82%E7%83%A9/" class="category-list-link">技术杂烩</a><span class="category-list-count">4</span></li>
            <li class="category-list-item"><a href="https://rulerLwx.gitee.io/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/" class="category-list-link">数据库</a><span class="category-list-count">15</span></li>
        </ul>
    </div>
</div>
      <div class="widget">
    <h3 class="widget-title"> Tags</h3>
    <div class="widget-body">
        <ul class="tag-list">
            
            
            <li class="tag-list-item"><a href="https://rulerLwx.gitee.io/tags/jvm/" class="tag-list-link">jvm</a><span
                    class="tag-list-count">1</span></li>
            
            
            <li class="tag-list-item"><a href="https://rulerLwx.gitee.io/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" class="tag-list-link">多线程</a><span
                    class="tag-list-count">2</span></li>
            
            
            <li class="tag-list-item"><a href="https://rulerLwx.gitee.io/tags/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/" class="tag-list-link">网络编程</a><span
                    class="tag-list-count">3</span></li>
            
        </ul>

    </div>
</div>
      
<div class="widget">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget-body">
        <ul class="recent-post-list list-unstyled no-thumbnail">
            <li>
                <div class="item-inner">
                    <p class="item-title">
                        <a href="https://rulerLwx.gitee.io/2020/07/%E8%87%AA%E5%B7%B1%E5%8A%A8%E6%89%8B%E4%B8%80%E6%89%B9%E9%87%8F%E7%A7%BB%E5%8A%A8%E9%87%8D%E5%91%BD%E5%90%8D%E6%96%87%E4%BB%B6/" class="title">自己动手（一）——批量移动、重命名文件</a>
                    </p>
                    <p class="item-date">
                        <time datetime="2020-07-27 17:50:02 &#43;0800 CST" itemprop="datePublished">2020-07-27</time>
                    </p>
                </div>
            </li>
            <li>
                <div class="item-inner">
                    <p class="item-title">
                        <a href="https://rulerLwx.gitee.io/2020/07/%E5%85%B3%E4%BA%8Einteger%E7%9A%84-128~127%E7%BC%93%E5%AD%98/" class="title">关于Integer的 -128~127缓存</a>
                    </p>
                    <p class="item-date">
                        <time datetime="2020-07-11 16:56:21 &#43;0800 CST" itemprop="datePublished">2020-07-11</time>
                    </p>
                </div>
            </li>
            <li>
                <div class="item-inner">
                    <p class="item-title">
                        <a href="https://rulerLwx.gitee.io/2020/07/%E8%B7%A8%E5%9F%9F%E9%97%AE%E9%A2%98/" class="title">跨域问题</a>
                    </p>
                    <p class="item-date">
                        <time datetime="2020-07-08 22:41:12 &#43;0800 CST" itemprop="datePublished">2020-07-08</time>
                    </p>
                </div>
            </li>
            <li>
                <div class="item-inner">
                    <p class="item-title">
                        <a href="https://rulerLwx.gitee.io/2020/07/%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2%E6%90%AD%E5%BB%BA/" class="title">个人博客搭建</a>
                    </p>
                    <p class="item-date">
                        <time datetime="2020-07-05 18:58:47 &#43;0800 CST" itemprop="datePublished">2020-07-05</time>
                    </p>
                </div>
            </li>
            <li>
                <div class="item-inner">
                    <p class="item-title">
                        <a href="https://rulerLwx.gitee.io/2020/07/centos/" class="title">CentOS-</a>
                    </p>
                    <p class="item-date">
                        <time datetime="2020-07-01 18:58:47 &#43;0800 CST" itemprop="datePublished">2020-07-01</time>
                    </p>
                </div>
            </li>
        </ul>
    </div>
</div>
  </div>
</aside>

    
    
<aside class="sidebar sidebar-toc collapse" id="collapseToc" itemscope itemtype="http://schema.org/WPSideBar">
  <div class="slimContent">
    <h4 class="toc-title">Catalogue</h4>
    <nav id="toc" class="js-toc toc">

    </nav>
  </div>
</aside>
<main class="main" role="main"><div class="content">
  <article id="-" class="article article-type-" itemscope
    itemtype="http://schema.org/BlogPosting">
    
    <div class="article-header">
      <h1 itemprop="name">
  <a
    class="article-title"
    href="/2020/07/java-se-%E5%A4%9A%E7%BA%BF%E7%A8%8B-2-%E9%AB%98%E7%BA%A7/"
    >Java-Se-多线程-2-高级</a
  >
</h1>

      <div class="article-meta">
        
<span class="article-date">
  <i class="icon icon-calendar-check"></i>&nbsp;
<a href="https://rulerLwx.gitee.io/2020/07/java-se-%E5%A4%9A%E7%BA%BF%E7%A8%8B-2-%E9%AB%98%E7%BA%A7/" class="article-date">
  <time datetime="2020-07-01 18:58:47 &#43;0800 CST" itemprop="datePublished">2020-07-01</time>
</a>
</span>
<span class="article-category">
  <i class="icon icon-folder"></i>&nbsp;
  <a class="article-category-link" href="/categories/java-se/"> Java-Se </a>
</span>  
  <span class="article-tag">
    <i class="icon icon-tags"></i>&nbsp;
    <a class="article-tag-link" href="/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/"> 多线程 </a>
  </span>

        <span class="post-comment"><i class="icon icon-comment"></i>&nbsp;<a href="/2020/07/java-se-%E5%A4%9A%E7%BA%BF%E7%A8%8B-2-%E9%AB%98%E7%BA%A7/#comments"
            class="article-comment-link">Comments</a></span>
		<span class="post-wordcount hidden-xs" itemprop="wordCount">Word Count: 3821words</span>
		<span class="post-readcount hidden-xs" itemprop="timeRequired">Read Count: 8minutes </span>
      </div>
    </div>
    <div class="article-entry marked-body js-toc-content" itemprop="articleBody">
      <h1 id="cas">CAS</h1>
<h2 id="cas-是什么">CAS 是什么</h2>
<p>compareAndSet()方法，也就是 compareAndSwap ，比较并且交换。</p>
<p>使用示例：</p>
<pre><code>    AtomicInteger atomicInteger = new AtomicInteger(5);
    //当前值是5，如果主内存中的值还是5则设置当前值为2019
    System.out.println(atomicInteger.compareAndSet(5, 2019)+&quot; current value:&quot;+ atomicInteger.get());
    
    atomicInteger.getAndIncrement();//代替 i++
</code></pre>
<h2 id="底层原理">底层原理</h2>
<p>Unsafe 类 是 CAS 的核心类，由于Java方法无法直接访问底层系统，需要通过本地（native）方法来访问，Unsafe相当于一个后门，基于该类可以直接操作特定内存的数据。Unsafe类存在于sun.misc包中，其内部方法操作可以像C的指针一样直接操作内存，因为Java中CAS操作的执行依赖于Unsafe类的方法。<strong>注意Unsafe类中的所有方法都是native修饰的，也就是说Unsafe类中的方法都直接调用操作系统底层资源执行相应任务</strong>。</p>
<p>变量valueOffset，<strong>表示该变量在内存中的偏移地址</strong>（类似于坐位的第三排第2位的说法），因为Unsafe就是根据内存偏移地址获取数据的。</p>
<p>变量value用volatile修饰，保证了多线程之间的内存可见性。</p>
<p>AtomicInteger：</p>
<pre><code class="language-java">    /**
     * Atomically increments by one the current value.
     *
     * @return the previous value
     */
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }
</code></pre>
<p>Unsafe：</p>
<pre><code>    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);// 底层代码，C 语言
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));// 底层代码，C 语言

        return var5;
    }
</code></pre>
<p>以上方法是交换的核心方法。</p>
<h2 id="缺点">缺点</h2>
<ul>
<li>循环时间长时开销大</li>
<li>只能保证一个共享变量的原子操作</li>
<li>引出ABA问题？？？</li>
</ul>
<h2 id="aba问题">ABA问题</h2>
<p>A是头尾的值，只要头尾值相同就交换。但在交换中间的时间里，有可能被其它的线程修改过A的值，只不过最后的值又恰巧修改回了A。</p>
<p>解决办法：使用原子引用，常用API：<code>AtomicReference</code>、<code>AtomicStampedReference</code></p>
<p>原理：原子引用 + 版本号&quot;stamp&rdquo;</p>
<p>以下是ABA问题的出现与解决：</p>
<pre><code class="language-java">public class ABADemo {

    static AtomicReference&lt;Integer&gt; atomicReference = new AtomicReference&lt;Integer&gt;(100);
    // AtomicStampedReference(V initialRef, int initialStamp)，initialRef 初始值，initialStamp 版本或时间戳
    static AtomicStampedReference&lt;Integer&gt; atomicStampedReference = new AtomicStampedReference&lt;&gt;(100, 1);

    public static void main(String[] args) {
        System.out.println(&quot;--------------以下是ABA问题的产生----------------&quot;);
        new Thread(()-&gt;{
            atomicReference.compareAndSet(100, 101);
            atomicReference.compareAndSet(101, 100);
        },&quot;t1&quot;).start();
        new Thread(()-&gt;{
            // 暂停1秒仲，目的是让t1执行一次ABA操作
            try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}
            boolean b = atomicReference.compareAndSet(100, 2019);
            System.out.println(b);
        },&quot;t2&quot;).start();

        // 暂停2秒仲，目的是让上面的ABA问题操作执行完成
        try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}

        System.out.println(&quot;--------------以下是ABA问题的解决----------------&quot;);

        new Thread(()-&gt;{
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+&quot;\t 第1次版本号：&quot;+stamp);
            // 暂停1秒仲t3线程
            try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}
            atomicStampedReference.compareAndSet(100, 101,
                    atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
            System.out.println(Thread.currentThread().getName()+&quot;\t 第2次版本号：&quot;+atomicStampedReference.getStamp());
            atomicStampedReference.compareAndSet(101, 100,
                    atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
            System.out.println(Thread.currentThread().getName()+&quot;\t 第3次版本号：&quot;+atomicStampedReference.getStamp());
        },&quot;t3&quot;).start();
        new Thread(()-&gt;{
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+&quot;\t 第1次版本号：&quot;+stamp);
            // 暂停3秒仲t4线程，目的是让t3执行完成
            try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}
            boolean b = atomicStampedReference.compareAndSet(100, 2019,
                    stamp, stamp + 1);
            System.out.println(Thread.currentThread().getName()+&quot;\t修改结果：&quot;+ b
                    +&quot;\t当前的实际版本号：&quot;+atomicStampedReference.getStamp());
        },&quot;t4&quot;).start();
    }
}
</code></pre>
<p>输出：</p>
<pre><code>--------------以下是ABA问题的产生----------------
true
--------------以下是ABA问题的解决----------------
t3	 第1次版本号：1
t4	 第1次版本号：1
t3	 第2次版本号：2
t3	 第3次版本号：3
t4	修改结果：false	当前的实际版本号：3
</code></pre>
<h1 id="集合类不安全的问题">集合类不安全的问题</h1>
<h2 id="为什么集合不安全">为什么集合不安全</h2>
<p>ArrayList 默认大小：10
HashMap 默认大小：16</p>
<p>为什么ArrayList线程不安全？</p>
<p>因为它的写方法没有加synchronized，ArrayList源码：</p>
<pre><code class="language-java">    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return &lt;tt&gt;true&lt;/tt&gt; (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
</code></pre>
<p>手写不安全示例：</p>
<pre><code class="language-java">    public static void main(String[] args) {
        List&lt;String&gt; list = new ArrayList&lt;&gt;();
        for (int i = 0; i &lt; 3; i++) {
            new Thread(()-&gt;{
                list.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
</code></pre>
<p>输出是随机的，以下是其中的两次输出：</p>
<pre><code>[null, null, 3e48b54b]
[null, null, 3e48b54b]
[null, null, 3e48b54b]

[null, c1bbced9]
[null, c1bbced9, 7da1e5a3]
[null, c1bbced9]
</code></pre>
<p>线程多时，可能还出现<code>java.util.ConcurrentModificationException</code>异常</p>
<h2 id="导致的原因">导致的原因</h2>
<p>一个人在写，另一个人过来抢夺，导致数据不一致。</p>
<h2 id="解决方案">解决方案</h2>
<ul>
<li><code>new Vector&lt;&gt;();</code>使用线程安全的 Vector 替换 ArrayList</li>
<li><code>Collections.synchronizedList(new ArrayList&lt;&gt;());</code> 将 ArrayList 包装成线程安全的</li>
<li><code>new CopyOnWriteArrayList&lt;&gt;()</code></li>
</ul>
<hr>
<p>CopyOnWriteArrayList 是“写时复制”，读写分离思想:</p>
<p><img src="https://gitee.com/leafsing/pic/raw/master/img/20200709233122.png" alt=""></p>
<p>CopyOnWriteArrayList源码：</p>
<pre><code class="language-java">    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);// 扩容1个元素
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }
</code></pre>
<h2 id="优化建议">优化建议</h2>
<p>使用“写时复制”，如：</p>
<ul>
<li><code>CopyOnWriteArrayList</code>替换<code>ArrayList</code></li>
<li><code>CopyOnWriteArraySet</code>替换<code>ArraySet</code></li>
<li><code>ConcurrentHashMap</code> 替换<code>HashMap</code></li>
<li><code>ConcurrentSkipListMap</code>替换<code>TreeMap</code></li>
</ul>
<h1 id="synchronized和lock有什么区别">synchronized和lock有什么区别</h1>
<ul>
<li>synchronized属于JVM层面，是java的关键字；lock是具体类，是api层面</li>
<li>synchronized不需要手动释放锁，lock需要手动释放锁</li>
<li>synchronized不可中断，除非抛出异常或正常运行完成；lock可以中断，方法一：设置超时时间<code>tryLock(long timeout, TimeUnit unit)</code>，方法二：<code>lockInterruptibly()</code>放代码块中，调用<code>interrupt()</code>方法可中断</li>
<li>synchronized非公平锁；ReentrantLock两者都可以，默认是非公平锁，构造方法可以传入boolean值，true为公平锁，false为非公平锁</li>
<li>ReentrantLock可以实现精确唤醒，而synchronized要么随机唤醒一个或全部唤醒</li>
<li>synchronized 锁住的是 this 或 某个字段，lock 锁住的是它内部的一个对象？？？？——20191024 <a href="https://www.iteye.com/problems/95328">https://www.iteye.com/problems/95328</a></li>
</ul>
<blockquote>
<p>面试题目<!-- raw HTML omitted --><!-- raw HTML omitted -->
多线程之间按顺序调用，实现A-&gt;B-C三个线程启动，要求如下：<!-- raw HTML omitted -->
AA打印5次，BB打印10次，CC打印15次，<!-- raw HTML omitted -->
紧接着，<!-- raw HTML omitted -->
AA打印5次，BB打印10次，CC打印15次，<!-- raw HTML omitted -->
&hellip;<!-- raw HTML omitted --></p>
<p>来10轮</p>
</blockquote>
<p>代码实现：</p>
<pre><code class="language-java">class ShareResource{
    private int number = 1;// A:1,B:2,C:3
    private Lock lock = new ReentrantLock();
    private Condition c1 = lock.newCondition();
    private Condition c2 = lock.newCondition();
    private Condition c3 = lock.newCondition();

    void print5(){
        lock.lock();
        try {
            // 1 判断
            while (number != 1) {
                c1.await();
            }
            // 2 干活
            for (int i = 1; i &lt;= 5; i++) {
                System.out.println(Thread.currentThread().getName()+&quot;\t&quot;+i);
            }
            // 3 通知
            number = 2;
            c2.signal();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    void print10(){
        lock.lock();
        try {
            // 1 判断
            while (number != 2) {
                c2.await();
            }
            // 2 干活
            for (int i = 1; i &lt;= 10; i++) {
                System.out.println(Thread.currentThread().getName()+&quot;\t&quot;+i);
            }
            // 3 通知
            number = 3;
            c3.signal();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    void print15(){
        lock.lock();
        try {
            // 1 判断
            while (number != 3) {
                c3.await();
            }
            // 2 干活
            for (int i = 1; i &lt;= 15; i++) {
                System.out.println(Thread.currentThread().getName()+&quot;\t&quot;+i);
            }
            // 3 通知
            number = 1;
            c1.signal();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}
public class SyncAndReentrantLockDemo {
    public static void main(String[] args) {
        ShareResource shareResource = new ShareResource();
        new Thread(()-&gt;{
            for (int i = 0; i &lt; 10; i++) {
                shareResource.print5();
            }
        },&quot;A&quot;).start();
        new Thread(()-&gt;{
            for (int i = 0; i &lt; 10; i++) {
                shareResource.print10();
            }
        },&quot;B&quot;).start();
        new Thread(()-&gt;{
            for (int i = 0; i &lt; 10; i++) {
                shareResource.print15();
            }
        },&quot;C&quot;).start();
    }
}
</code></pre>
<p>锁绑定多个Condition</p>
<h1 id="公平锁非公平锁乐观锁悲观锁">公平锁、非公平锁、乐观锁、悲观锁</h1>
<ul>
<li>公平锁：加锁前先查看是否有<strong>排队</strong>等待的线程，有的话优先处理排在前面的线程，<strong>先来先得</strong></li>
<li>非公平锁：线程加锁时直接尝试获取锁，获取不到就自动到队尾等待</li>
<li>乐观锁</li>
<li>悲观锁</li>
</ul>
<p>总结：</p>
<ul>
<li>更多的是直接使用非公平锁：非公平锁比公平锁性能高5-10倍，因为公平锁需要在多核情况下维护一个队列，如果当前线程不是队列的第一个无法获取锁，增加了线程切换次数 ——20191111</li>
</ul>
<p>参考：https://www.cnblogs.com/darrenqiao/p/9211178.html</p>
<h1 id="多线程下的单例">多线程下的单例</h1>
<p>单线程下的懒汉模式：</p>
<pre><code class="language-java">public class SingleInstanceTest {
    private SingleInstanceTest(){
        System.out.println(&quot;这是SingleInstanceTest()&quot;);
    }
    public static SingleInstanceTest instance;

    public static SingleInstanceTest getInstance() {
        if (instance == null) {
            instance = new SingleInstanceTest();
        }
        return instance;
    }
}
</code></pre>
<p>解决办法：</p>
<ul>
<li>获取实例的<code>getInstance()</code>方法使用<code>synchronized</code>修饰，不推荐</li>
<li>双重锁方式（DCL，double check lock）并使用<code>volatile</code>关键字，推荐</li>
</ul>
<pre><code class="language-java">public class DoubleCheckLockSingleInstanceTest {
    private volatile static DoubleCheckLockSingleInstanceTest instance;

    private DoubleCheckLockSingleInstanceTest() {
        System.out.println(&quot;这是DoubleCheckLockSingleInstanceTest()&quot;);
    }

    public static DoubleCheckLockSingleInstanceTest getSingleton() {
        if (instance == null) {
            synchronized (DoubleCheckLockSingleInstanceTest.class) {
                if (instance == null) {
                    instance = new DoubleCheckLockSingleInstanceTest();
                }
            }
        }
        return instance;
    }
}
</code></pre>
<p>另外，可参考笔记《Java-Senior-设计模式》</p>
<p><strong>注意</strong>：DCL（双重锁）机制不一定线程安全，原因是有指令重排序的存在，加入<code>volatile</code>可禁止指令重排。</p>
<h1 id="threadlocal">ThreadLocal</h1>
<p>示例：并发下的时间格式化</p>
<pre><code class="language-java">    private static final ThreadLocal&lt;DateFormat&gt; df = new ThreadLocal&lt;DateFormat&gt;() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat(&quot;yyyy-MM-dd&quot;);
        }
    };
</code></pre>
<p>参考《阿里巴巴java开发手册(最终版)》并发处理</p>
<p>Java并发编程——ThreadLocal：https://blog.csdn.net/ghw15221836342/article/details/100136753</p>
<h1 id="volatile">volatile</h1>
<p>参考笔记《Java-Se-关键字》</p>
<h1 id="string--stringbuffer--stringbuilder">String &amp; StringBuffer &amp; StringBuilder</h1>
<ul>
<li>String 是不可变类，StringBuffer、StringBuilder是可变</li>
<li>String、StringBuffer 是线程安全的（所有不可变类都是线程安全的，线程安全的类不一定是不可变类，如StringBuffer是可变类，靠方法上都加了synchronized锁实现线程安全；String内部存储字符串的char数组以及和char数组相关的信息都是final的来实现线程安全）</li>
</ul>

    </div>
    <div class="article-footer">
<blockquote class="mt-2x">
  <ul class="post-copyright list-unstyled">
    <li class="post-copyright-link hidden-xs">
      <strong>Permalink: </strong>
      <a href="https://rulerLwx.gitee.io/2020/07/java-se-%E5%A4%9A%E7%BA%BF%E7%A8%8B-2-%E9%AB%98%E7%BA%A7/" title="Java-Se-多线程-2-高级" target="_blank" rel="external">https://rulerLwx.gitee.io/2020/07/java-se-%E5%A4%9A%E7%BA%BF%E7%A8%8B-2-%E9%AB%98%E7%BA%A7/</a>
    </li>
    <li class="post-copyright-license">
      <strong>License：</strong><a href="http://creativecommons.org/licenses/by/4.0/deed.zh" target="_blank" rel="external">CC BY 4.0 CN</a>
    </li>
  </ul>
</blockquote>

<div class="panel panel-default panel-badger">
  <div class="panel-body">
    <figure class="media">
      <div class="media-left">
        <a href="https://gitee.com/rulerLwx" target="_blank" class="img-burn thumb-sm visible-lg">
          <img src="https://rulerLwx.gitee.io/avatar.png" class="img-rounded w-full" alt="">
        </a>
      </div>
      <div class="media-body">
        <h3 class="media-heading"><a href="https://gitee.com/rulerLwx" target="_blank"><span class="text-dark">rulerLwx</span><small class="ml-1x">thinking...</small></a></h3>
        <div>Good Good Study, Day Day Up~</div>
      </div>
    </figure>
  </div>
</div>
    </div>
  </article>
<section id="comments">
    <div id="vcomments"></div>
</section>

</div><nav class="bar bar-footer clearfix" data-stick-bottom>
    <div class="bar-inner">
        <ul class="pager pull-left">
            <li class="prev">
                <a href="https://rulerLwx.gitee.io/2020/07/java-se-%E5%BA%8F%E5%88%97%E5%8C%96/" title="Java-Se-序列化"><i
                        class="icon icon-angle-left"
                        aria-hidden="true"></i><span>&nbsp;&nbsp;Older</span></a>
            </li>
            <li class="next">
                <a href="https://rulerLwx.gitee.io/2020/07/java-se-%E5%A4%9A%E7%BA%BF%E7%A8%8B-1-%E5%9F%BA%E7%A1%80/"
                    title="Java-Se-多线程-1-基础"><span>Newer&nbsp;&nbsp;</span><i
                        class="icon icon-angle-right" aria-hidden="true"></i></a>
            </li>
            
            <li class="toggle-toc">
                <a class="toggle-btn collapsed" data-toggle="collapse" href="#collapseToc" aria-expanded="false"
                    title="Catalogue" role="button">
                    <span>[&nbsp;</span><span>Catalogue</span>
                    <i class="text-collapsed icon icon-anchor"></i>
                    <i class="text-in icon icon-close"></i>
                    <span>]</span>
                </a>
            </li>
        </ul>
        <div class="bar-right">
            <div class="share-component" data-sites="weibo,qq,wechat"
                data-mobile-sites="weibo,qq,qzone"></div>
        </div>
    </div>
</nav>

</main><footer class="footer" itemscope itemtype="http://schema.org/WPFooter">
<ul class="social-links">
    <li><a href="https://gitee.com/rulerLwx" target="_blank" title="gitee" data-toggle=tooltip data-placement=top >
            <i class="icon icon-gitee"></i></a></li>
    <li><a href="https://github.com/wolf-lea" target="_blank" title="github" data-toggle=tooltip data-placement=top >
            <i class="icon icon-github"></i></a></li>
</ul>
  <div class="copyright">
    &copy;2020  -
    2020
    <div class="publishby">
        Theme by <a href="https://github.com/xiaoheiAh" target="_blank"> xiaoheiAh </a>base on<a href="https://github.com/xiaoheiAh/hugo-theme-pure" target="_blank"> pure</a>.
    </div>
  </div>
</footer>

<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-MML-AM_SVG"></script>
<script type="text/x-mathjax-config">
    MathJax.Hub.Config({
            showMathMenu: false, //disables context menu
            tex2jax: {
            inlineMath: [ ['$','$'], ['\\(','\\)'] ]
           }
    });
</script>


<script src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.min.js"></script>
<script>
    window.jQuery || document.write('<script src="js/jquery.min.js"><\/script>')
</script>
<script type="text/javascript" src="https://cdn.staticfile.org/highlight.js/9.15.10/highlight.min.js"></script>
<script type="text/javascript" src="https://cdn.staticfile.org/highlight.js/9.15.10/languages/python.min.js" defer></script>
<script type="text/javascript" src="https://cdn.staticfile.org/highlight.js/9.15.10/languages/javascript.min.js" defer></script><script>
    hljs.configure({
        tabReplace: '    ', 
        classPrefix: ''     
        
    })
    hljs.initHighlightingOnLoad();
</script>
<script src="https://rulerLwx.gitee.io/js/application.min.bdeb64b910570b6c41badc6a05b7afb0c8ad9efd8525de3c7257d59e786326a3.js"></script>
<script src="https://rulerLwx.gitee.io/js/plugin.min.51ff8c7317566f82259170fa36e09c4493adc9b9378b427a01ad3f017ebac7dd.js"></script>

<script>
    (function (window) {
        var INSIGHT_CONFIG = {
            TRANSLATION: {
                POSTS: 'Posts',
                PAGES: 'Pages',
                CATEGORIES: 'Categories',
                TAGS: 'Tags',
                UNTITLED: '(Untitled)',
            },
            ROOT_URL: 'https:\/\/rulerLwx.gitee.io',
            CONTENT_URL: 'https:\/\/rulerLwx.gitee.io\/searchindex.json ',
        };
        window.INSIGHT_CONFIG = INSIGHT_CONFIG;
    })(window);
</script>
<script type="text/javascript" src="https://rulerLwx.gitee.io/js/insight.min.a343cd9a5a7698336b28ef3a7c16a3a1b1d2d5fb17dc8ed04022bbe08cc5459073a15bdafa3a8a58cdd56080784bdd69fa70b1ae8597565c799c57ed00f0e120.js" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.4.2/tocbot.min.js"></script>
<script>
    tocbot.init({
        
        tocSelector: '.js-toc',
        
        contentSelector: '.js-toc-content',
        
        headingSelector: 'h1, h2, h3',
        
        hasInnerContainers: true,
    });
</script>

<script src="https://cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/valine"></script>
<script type="text/javascript">
    var GUEST = ['nick', 'mail', 'link'];
    var meta = 'nick,mail';
    meta = meta.split(',').filter(function (item) {
        return GUEST.indexOf(item) > -1;
    });
    new Valine({
        el: '#vcomments',
        verify: null ,
        notify: null ,
        appId: 'IyAB0PSPRazTPDxitO1ddQ7O-gzGzoHsz',
        appKey: '5rBJTq4KidYF33eXwvRVhtEH',
        placeholder: 'enjoy~',
        avatar: 'mm',
        meta: meta,
        pageSize: '10' || 10,
        visitor: false 
});
</script>

  </body>
</html>
